package cn.maihe.elg.operation.centers.epoint.handler.service;

import cn.maihe.elg.operation.centers.epoint.config.EpointCenterInfosConfig;
import cn.maihe.elg.operation.centers.epoint.dto.EpointBaseRespDTO;
import cn.maihe.elg.operation.centers.epoint.dto.handler.EpointApplyGuaranteeReq;
import cn.maihe.elg.operation.centers.epoint.dto.handler.EpointApplyGuaranteeResp;
import cn.maihe.elg.operation.centers.epoint.enums.EpointRespCodeEnum;
import cn.maihe.elg.operation.centers.epoint.handler.EpointCenterTradeService;
import cn.maihe.elg.operation.centers.supports.CenterTradeContext;
import cn.maihe.elg.operation.centers.supports.annotation.CenterTradeService;
import cn.maihe.elg.operation.model.bo.AcceptOrderBO;
import cn.maihe.elg.operation.model.bo.ApplyTemplatePdfParams;
import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.AttachmentFileType;
import cn.maihe.elg.operation.model.enums.BidCustomerStatus;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.CenterProviderEnum;
import cn.maihe.elg.operation.model.enums.GuaranteeCategory;
import cn.maihe.elg.operation.model.enums.GuaranteeType;
import cn.maihe.elg.operation.model.enums.IDType;
import cn.maihe.elg.operation.model.enums.InstitutionOrgCodeEnum;
import cn.maihe.elg.operation.model.enums.TradeType;
import cn.maihe.elg.operation.model.enums.UserStatusEnum;
import cn.maihe.elg.operation.model.enums.UserType;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.BidCustomerDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeInstitutionDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDO;
import cn.maihe.elg.operation.repository.entity.UserDO;
import cn.maihe.elg.operation.service.business.BidCustomerService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.GuaranteeAttachmentInfoService;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.AutoDiscernTemplateUtil;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.IdGenerate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.Date;

/**
 * @Description 提供申请保函接口
 * @Author WJH
 * @Date 2021/04/22
 */
@CenterTradeService(
        provider = CenterProviderEnum.EPOINT,
        centerNo = CenterNoEnum.NANPING,
        tradeType = TradeType.baohanapply,
        reqClass = EpointApplyGuaranteeReq.class,
        respClass = EpointApplyGuaranteeResp.class
)
@Slf4j
public class NPEpointBaohanApplyService extends EpointCenterTradeService<EpointApplyGuaranteeReq, EpointApplyGuaranteeResp> {
    public NPEpointBaohanApplyService(EpointCenterInfosConfig centerInfosConfig) {
        super(centerInfosConfig);
    }

    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private ElgResourceService elgResourceService;
    @Resource
    private GuaranteeAttachmentInfoService guaranteeAttachmentInfoService;
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private BidCustomerService bidCustomerService;

    @Override
    protected void verifyParam(CenterTradeContext<EpointApplyGuaranteeReq, EpointApplyGuaranteeResp> context) {
        super.verifyParam(context);
        EpointApplyGuaranteeReq req = context.getReq();
        String orderNo = req.getApplyno();
        boolean exists = acceptOrderInfoService.existsCenterOrderId(context.getCenterId(), orderNo);
        Assert.isTrue(!exists, () -> "中心订单编号已存在");
    }

    @Override
    public EpointApplyGuaranteeResp processService(CenterTradeContext<EpointApplyGuaranteeReq, EpointApplyGuaranteeResp> context) {

        AcceptOrderBO acceptOrderBO = this.parseApplyGuaranteeInfo(context);

        EpointApplyGuaranteeResp resp = new EpointApplyGuaranteeResp();
        try {
            bidCustomerService.checkBidderContractInfo(acceptOrderBO.getBidCustomer());
        } catch (Exception e) {
            resp.setCode(EpointRespCodeEnum.FAILURE.getRespCode());
            resp.setMessage(e.getMessage());
            return resp;
        }

        acceptOrderBO = acceptOrderInfoService.saveAcceptOrderBO(acceptOrderBO);

        resp = buildResp(acceptOrderBO);
        return resp;
    }

    private EpointApplyGuaranteeResp buildResp(AcceptOrderBO acceptOrderBO) {
        EpointApplyGuaranteeResp resp = EpointBaseRespDTO.success("受理成功", EpointApplyGuaranteeResp.class);
        //投标企业是否已提交企业认证资料且已审核通过
        BidCustomerDO bidCustomerDO = acceptOrderBO.getBidCustomer();

        // TODO 待配合前端优化 改为 信用代码+密码登录方式么
        if (BidCustomerStatus.NORMAL.getStatus() != bidCustomerDO.getStatus()) {
            //非正常状态跳转到投标人认证资料补充页面
            resp.setPayurl(elgResourceService.buildElgFrontUrl("/#/autoLogin?mobile=" + acceptOrderBO.getUserDO().getUsername() + "&ordersn=" + acceptOrderBO.getAcceptOrderInfo().getAcceptOrderNo()));
        } else {
            resp.setPayurl(elgResourceService.buildElgFrontUrl("/#/autoLogin?mobile=" + acceptOrderBO.getUserDO().getUsername() + "&ordersn=" + acceptOrderBO.getAcceptOrderInfo().getAcceptOrderNo()));
        }
        //跳转到该订单上传申请书&反担保协议书 及 支付凭证页面
        makeAndSaveApplyFile(acceptOrderBO);
        return resp;
    }

    /**
     * docx模板合成申请书
     */
    private void makeAndSaveApplyFile(AcceptOrderBO acceptOrderBO) {
        ApplyTemplatePdfParams params = new ApplyTemplatePdfParams();
        params.setBidderName(acceptOrderBO.getBidCustomer().getBidderName());
        params.setProjectName(acceptOrderBO.getProjectInfo().getProjectName());
        Triple<String, String, String> triple = DateUtil.parseLocalDate();
        params.setYear(triple.getLeft());
        params.setMonth(triple.getMiddle());
        params.setDay(triple.getRight());
        AcceptOrderInfoDO orderInfo = acceptOrderBO.getAcceptOrderInfo();
        String acceptOrderNo = orderInfo.getAcceptOrderNo();
        Path docxPath = elgResourceService.buildApplyFileByTemplate(acceptOrderNo, params);

        guaranteeAttachmentInfoService.saveOrUpdateAttachmentInfo(orderInfo, docxPath, AttachmentFileType.TYPE_12, "申请书未签章");

    }


    /**
     * 解析 受理的清单信息
     */
    private AcceptOrderBO parseApplyGuaranteeInfo(CenterTradeContext<EpointApplyGuaranteeReq, EpointApplyGuaranteeResp> context) {
        EpointApplyGuaranteeReq req = context.getReq();
        long centerId = context.getCenterId();
        long orgId = context.getOrgId();
        //固定中天担保直开式
        InstitutionOrgCodeEnum institutionOrgCodeEnum = InstitutionOrgCodeEnum.resolve(context.getOrgCode());
//        InstitutionCode curInstitutionCode = InstitutionCode.deXing;
        GuaranteeInstitutionDO institutionDO = getInstitutionIdByCode(institutionOrgCodeEnum);
        String acceptOrderNo = IdGenerate.genAcceptOrderNo(context.getCenterNoEnum());

        ProjectInfoDO projectInfoDO = this.buildProjectInfo(context.getCenterNoEnum(),req, centerId, orgId);
        BidCustomerDO bidCustomerDO = this.buildBidCustomerInfo(req, centerId, orgId);
        UserDO userDO = this.buildUserInfo(req, centerId, orgId);
        AcceptOrderInfoDO acceptOrderInfoDO = this.buildAcceptOrderInfo(acceptOrderNo, req, centerId, orgId, institutionDO);
        //计算保费
        String feeRate = this.getCurCenterInfo(context).getFeeRate();
        acceptOrderInfoDO.setFeeRate(feeRate);
        String minFeeYuan = this.getCurCenterInfo(context).getMinFeeYuan();
        acceptOrderInfoDO.setGuaranteeFee(this.calcGuaranteeFee(projectInfoDO.getBidBond(), feeRate, minFeeYuan));

        AcceptOrderBO orderBO = AcceptOrderBO.builder().centerId(centerId).orgId(orgId)
                .acceptOrderInfo(acceptOrderInfoDO).projectInfo(projectInfoDO).bidCustomer(bidCustomerDO).userDO(userDO).build();

        //默认投标保函类别;
        orderBO.setGuaranteeCategory(GuaranteeCategory.BID);
        //默认担保公司担保类型;
        orderBO.setGuaranteeType(GuaranteeType.GUARANTEE);

        orderBO.setInstitutionOrgCodeEnum(institutionOrgCodeEnum);
        orderBO.setIsInnerApply(false);

        //出函机构赋值
        acceptOrderInfoDO.setInstitutionId(institutionDO.getId());
        acceptOrderInfoDO.setGuaranteeType(orderBO.getGuaranteeType().getTypeStr());
        acceptOrderInfoDO.setGuaranteeCategory(orderBO.getGuaranteeCategory().getCategoryStr());


        return orderBO;
    }


    private AcceptOrderInfoDO buildAcceptOrderInfo(String acceptOrderNo, EpointApplyGuaranteeReq req, long centerId, long orgId, GuaranteeInstitutionDO institutionDO) {
        return AcceptOrderInfoDO.builder()
                .centerId(centerId).orgId(orgId)
                .guaranteeNo(IdGenerate.genGuaranteeNo(institutionDO.getInstitutionCode()))
                .centerOrderId(req.getApplyno())
                .centerOrderTime(DateUtil.getDatetime())
                .acceptOrderNo(acceptOrderNo)
                .projectName(req.getProjectname())
                .sectionName(req.getBiaoduanname())
                .bidCustomerName(req.getBiddername())
                //当前投标期限保证金截止时间
                .bidIndate(DateUtil.parseDate(req.getBzjendtime(), "yyyy-MM-dd HH:mm:ss"))
                .guaranteeType(null)//'保函类型'
                .guaranteeCategory(null) //'保函品种'
                .templateId(null)//'报价模板主键id'
                .feeRate(null)
                .guaranteeFee(null)//'保费金额分'
                .status(AcceptOrderStatus.WAIT_PAY.getStatus())
                .guaranteeTime(null)
                .projectId(null)//  '投保项目主键id' 关联保存时统一设置
                .bidCustomerId(null)// '投保客户主键id'
                .institutionId(null) //'开函机构主键'
                .attachmentId(null)//
                .applyOrderNo(null)
                .invoiceFlag(null)
                .invoiceId(null)
                .warnFlag(0).warnContent(null)
                .gmtCreate(Date.from(Instant.now()))
                .build();
    }

    private BidCustomerDO buildBidCustomerInfo(EpointApplyGuaranteeReq req, long centerId, long orgId) {
        // 其他信息通过 企业认证补充页面收集
        return BidCustomerDO.builder()
                .centerId(centerId).orgId(orgId)
                .bidderName(req.getBiddername())
                .bidderCreditCode(req.getBiddercode())
                .bidderContactName(null)
                .bidderContactTel(null)
                .bidderContactIdcardType(IDType.ID_CARD.getType())
                .bidderContactIdcard(null)
                .bidderAddress(null)
                .bidderEamil(null)
                .legalPersonName(null)
                .legalPersonTel(null)
                .legalPersonIdcardType(IDType.ID_CARD.getType())
                .legalPersonIdcard(null)
                .enableAutoApprove(0) //'是否自动审批 0否 1是',
                .blacklistFlag(0) //'是否黑名单 0后 1是',*/
                .gmtCreate(Date.from(Instant.now())).build();

    }

    private UserDO buildUserInfo(EpointApplyGuaranteeReq req, long centerId, long orgId) {
        return UserDO.builder()
                .umLogin("0")
                .followId(req.getBiddercode())
                .username(req.getBiddercode())
                .mobileNo(null)//改成统一社会信用代码登录
                .name(req.getBiddername())
                .type(UserType.BIDDER.getType())
                .status(UserStatusEnum.NORMAL.name())
                .orgCode("-1")
                .gmtCreate(new Date())
                .gmtModified(new Date())
                .build();
    }

    private ProjectInfoDO buildProjectInfo(CenterNoEnum centerNoEnum,EpointApplyGuaranteeReq req, long centerId, long orgId) {
        return ProjectInfoDO.builder()
                .centerId(centerId).orgId(orgId)
                .projectCode(req.getProjectno()).projectName(req.getProjectname())
                .sectionCode(req.getBiaoduanno()).sectionName(req.getBiaoduanname())
                .contractReckonPrice(yuan2fenLong(req.getReckonprice()))
                .tenderer(req.getZbr())
                .tendererCreditCode(req.getZbrorgnum())
                .tendererBankOpenbank(req.getTendereropenbank())
                .tendererBankCode(req.getTendererbankcode())
                .tendererBankAccount(req.getTendererbankaccount())
                .tendererContact(req.getTenderercontact())
                .tendererContactTel(req.getTenderercontacttel())
                .cityCode(req.getCitycode())
                .tenderProjectType(req.getProjecttype())
                .bidOpenTime(DateUtil.parseDate(req.getKaibiaotime(), "yyyy-MM-dd HH:mm:ss"))//'开标时间'=投标截止日期
                .bidIndate(DateUtil.parseDate(req.getBzjendtime(), "yyyy-MM-dd HH:mm:ss"))
                .validPeriod(Integer.valueOf(req.getTbyxq()))//投标有效期（单位：天）
                .bidBond(yuan2fenLong(req.getBzjamount()))
                .tenderNoticeUrl(req.getTendernoticeurl())
                .tenderFileUrl(req.getTenderfileurl())
                .tenderFileMd5(genTenderFileMd5(req.getBiaoduanno(),req.getBiaoduanname(), centerId, orgId, req.getTenderfileurl()))//'招标方文件md5校验值'
                .tendererAddress(req.getZbraddress())
                .noticePubDate(StringUtils.isNotBlank(req.getZbfiledate())?DateUtil.parseDate(req.getZbfiledate(), "yyyy-MM-dd HH:mm:ss"):null)
                .templateId(AutoDiscernTemplateUtil.getTemplateIdByTenderProjectType(centerNoEnum,req.getProjecttype()))
                .remark(null)//无
                .warnFlag(0)// '预警标识0正常 1出函机构无法受理该项目',
                .sourceFlag(0)// '信息来源0自动 1手动',
                .gmtCreate(Date.from(Instant.now()))
                .build();
    }

    private String genTenderFileMd5(String sectionCode, String sectionName, Long centerId, Long orgId, String tenderFileUrl) {
        String tenderFileMd5 = null;
        try {
            if (!StringUtils.isEmpty(tenderFileUrl)) {
                ProjectInfoDO projectInfo = projectInfoService.getBySectionCode(sectionCode,sectionName, centerId, orgId);
                if (projectInfo == null || StringUtils.isEmpty(projectInfo.getTenderFileMd5())) {
                    //download file
                    Path tmpPath = elgResourceService.downloadByURL(tenderFileUrl);

                    String relativePath = elgResourceService.transferAndSaveFile(tmpPath, "ofd", "tenderFile", "标段" + sectionCode + "招标文件");
                    Path savePath = elgResourceService.getAbsolutePath(relativePath);
                    tenderFileMd5 = elgResourceService.getFileMD5AsHex(savePath);
                    try {
                        Files.deleteIfExists(tmpPath);
                    } catch (IOException e) {
                        log.error("删除临时招标文件异常：{}", e.getMessage(), e);
                    }
                } else {
                    tenderFileMd5 = projectInfo.getTenderFileMd5();
                }
            }
        } catch (Exception e) {
            log.error("下载招标文件失败：{}", e.getMessage(), e);
        }
        return tenderFileMd5;
    }


}
